package com.jianqiao.delivery.delivery.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.db.sql.Order;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.jianqiao.delivery.delivery.domain.DeliveryEntity;
import com.jianqiao.delivery.delivery.domain.TGlPackageDetailsEntity;
import com.jianqiao.delivery.delivery.domain.vo.DeliveryStatusVo;
import com.jianqiao.delivery.delivery.domain.vo.PackageStatusVo;
import com.jianqiao.delivery.delivery.mapper.CargoMapper;
import com.jianqiao.delivery.delivery.mapper.DeliveryMapper;
import com.jianqiao.delivery.delivery.service.DeliveryService;
import com.jianqiao.delivery.enums.OrderStatusEnum;
import com.jianqiao.delivery.enums.PackageStatusEnum;
import com.jianqiao.delivery.enums.ScanTypeEnum;
import com.jianqiao.delivery.qr.domain.QRCodeParameter;
import com.jianqiao.delivery.util.QrUtil;
import com.jianqiao.delivery.util.RedisUtils;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.TPointsLog;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.mapper.TPointsLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Path;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.*;

/**
 * author: cyx
 * create: 2024/5/24 17:49
 **/
@Slf4j
@Service
public class DeliveryServiceImpl extends ServiceImpl<DeliveryMapper, DeliveryEntity> implements DeliveryService {

    @Autowired
    private DeliveryMapper deliveryMapper;

    @Autowired
    private CargoMapper cargoMapper;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Value("${ruoyi.profile}")
    private String codePath;
    @Autowired
    private TPointsLogMapper tPointsLogMapper;

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(20);

    private Map<String ,ScheduledFuture<?>> scheduledFutureMap = new HashMap<>();

    /**
      *methood: 查询快递订单列表
      *auth: cyx
      *time: 2024/6/5 16:34
    **/
    @Override
    public Map<String, Object> selectDeliver(String statusCode , Integer pageNum , Integer pageSize ,String uid) {
        Double totalPrice = 0.0;
        PageHelper.startPage(pageNum ,pageSize);
        List<DeliveryEntity> deliveryList = deliveryMapper.selectDeliveryList(statusCode ,uid);
        Map<String, Object> resultMap = new HashMap<>();
        PageInfo<DeliveryEntity> deliveryPageInfo = new PageInfo<>(deliveryList);
        resultMap.put("deliveryPageInfo" ,deliveryPageInfo);
        resultMap.put("totalPrice" ,totalPrice);
        return resultMap;
    }

    @Override
    public DeliveryEntity selectDetail(String id) {
        DeliveryEntity delivery = deliveryMapper.selectDeliveryDetail(id);
        return delivery;
    }

    @Override
    public int cancelDelivery(String id) {
        LambdaUpdateWrapper<DeliveryEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(DeliveryEntity::getId ,id).set(DeliveryEntity::getDelFlag  ,"0");
        return deliveryMapper.update(null ,updateWrapper);
    }

    @Override
    public Map<String, Integer> countDelivery(String uid) {
        Integer waitInputInt = 0;
        Integer waitImproveInt = 0;
        Integer orderPayInt = 0;
        Integer waitOutputInt = 0;
        Integer confirmReceiptInt = 0;
        Integer receiveInt = 0;
        List<DeliveryEntity> deliveryEntityList = deliveryMapper.selectDeliveryList(null ,uid);
        for (DeliveryEntity delivery : deliveryEntityList){
            String status = delivery.getStatus();
            if ("0".equals(status)){
                waitInputInt ++;
            } else if("1".equals(status)){
                waitImproveInt ++;
            } else if("2".equals(status)){
                orderPayInt ++;
            } else if("3".equals(status)){
                waitOutputInt ++;
            } else if("4".equals(status)){
                confirmReceiptInt ++;
            } else if ("5".equals(status)){
                receiveInt ++;
            }
        }
        //初始化返回结果
        Map<String, Integer> resultMap = new HashMap<>();
        resultMap.put("waitInput" ,waitInputInt);
        resultMap.put("waitImprove" ,waitImproveInt);
        resultMap.put("orderPay" ,orderPayInt);
        resultMap.put("waitOutput" ,waitOutputInt);
        resultMap.put("confirmReceipt" ,confirmReceiptInt);
        resultMap.put("receiveInt" ,receiveInt);
        return resultMap;
    }

    /**
      *methood: 新增快递订单
      *auth: cyx
      *time: 2024/6/9 17:39
    **/
    @Override
    @Transactional
    public Integer insertDelivery(DeliveryEntity[] deliveryEntities ,String uid) {
        List<DeliveryEntity> deliveryList = new ArrayList<>();
        List<String> addressList = new ArrayList<>();
        List<DeliveryEntity> haveClearanceList = new ArrayList<>();
        List<DeliveryEntity> unClearanceList = new ArrayList<>();

        //遍历此次加入的快递包裹的地址，并形成地址列表
        for (int i = 0 ;i < deliveryEntities.length ;i++){
            String address = deliveryEntities[i].getAddress();
            if (!addressList.contains(address)){
                addressList.add(address);
            }
        }
        //先将快递包裹通过报关与否分为两个数组
        for (int i = 0 ;i < deliveryEntities.length ;i++){
            String customsClearance = deliveryEntities[i].getCustomsClearance();
            //分进报关列表中
            if ("1".equals(customsClearance)){
                haveClearanceList.add(deliveryEntities[i]);
            }
            //分进无报关列表中
            else {
                unClearanceList.add(deliveryEntities[i]);
            }
        }
        //遍历此次加入的快递包裹的数组，并将同一地址的、同一报关状态的包裹形成为同一订单
        Random random = new Random();
        for (int i = 0 ;i < addressList.size() ;i++){
            String nowAddress = addressList.get(i);
            if (!haveClearanceList.isEmpty()){
                DeliveryEntity haveClearanceEntity = differentiateOrders(haveClearanceList, nowAddress, uid);
                if (!haveClearanceEntity.getLists().isEmpty()){
                    String qrcodePath = this.createQrcode(haveClearanceEntity.getOrderNumber());
                    haveClearanceEntity.setQrcodeUrl(qrcodePath);
                    deliveryList.add(haveClearanceEntity);
                }
            }
            if (!unClearanceList.isEmpty()){
                DeliveryEntity unClearanceEntity = differentiateOrders(unClearanceList, nowAddress, uid);
                if (!unClearanceEntity.getLists().isEmpty()){
                    String qrcodePath = this.createQrcode(unClearanceEntity.getOrderNumber());
                    unClearanceEntity.setQrcodeUrl(qrcodePath);
                    deliveryList.add(unClearanceEntity);
                }
            }
        }
        //将目的国家的字段值翻译
        for (DeliveryEntity deliveryEntity : deliveryList) {
            String destinationCountry = deliveryEntity.getDestinationCountry();
            if ("フィリピン".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("フィリピン/菲律宾");
            } else if ("インドネシア".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("インドネシア/印度尼西亚");
            } else if ("マレーシア".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("マレーシア/马来西亚");
            } else if ("タイ".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("タイ/泰国");
            } else if ("ミャンマー".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("ミャンマー/缅甸");
            } else if ("カンボジア".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("カンボジア/柬埔寨");
            } else if ("ラオス".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("ラオス/老挝");
            } else if ("ベトナム".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("ベトナム/越南");
            } else if ("シンガポール".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("シンガポール/新加坡");
            } else if ("ブルネイ".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("ブルネイ/文莱");
            } else if ("Philippines".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Philippines/菲律宾");
            } else if ("Indonesia".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Indonesia/印度尼西亚");
            } else if ("Malaysia".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Malaysia/马来西亚");
            } else if ("Thailand".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Thailand/泰国");
            } else if ("Myanmar".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Myanmar/缅甸");
            } else if ("Cambodia".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Cambodia/柬埔寨");
            } else if ("Laos".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Laos/老挝");
            } else if ("Vietnam".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Vietnam/越南");
            } else if ("Singapore".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Singapore/新加坡");
            } else if ("Brunei".equals(destinationCountry)) {
                deliveryEntity.setDestinationCountry("Brunei/文莱");
            }
        }

        //插入Delivery表
        int insertCount = deliveryMapper.insertDelivery(deliveryList);
        //插入包裹表
        for (DeliveryEntity deliveryEntity : deliveryList){
            List<TGlPackageDetailsEntity> packageList = deliveryEntity.getLists();
            for (TGlPackageDetailsEntity packageDetails : packageList) {
                int id = random.nextInt(Integer.MAX_VALUE);
                packageDetails.setId(id);
                String barcodeUrl = createBarcode(deliveryEntity.getOrderNumber(), String.valueOf(id));
                packageDetails.setBarcodeUrl(barcodeUrl);
            }
            deliveryMapper.insertPackage(packageList);
        }

        //设置定时器
        for (DeliveryEntity deliveryEntity : deliveryList) {
            Integer id = deliveryEntity.getId();
            Runnable checkTask = () -> {
                log.info("Restart the timer for " + id);
                long expirationTimeInSeconds = 1800;
                LocalDateTime now = LocalDateTime.now();

                //从redis或数据库中查询该订单的状态是否为0-未支付
                String orderPayStatus = "";
                boolean hasKey = redisUtils.hasKey(id + "-orderPayStatus");
                if (hasKey){
                    orderPayStatus = redisUtils.get(id + "-orderPayStatus").toString();
                }
                else {
                    LambdaQueryWrapper<DeliveryEntity> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(DeliveryEntity::getId ,id);
                    orderPayStatus = deliveryMapper.selectOne(queryWrapper).getPayment().toString();
                    redisUtils.set(id + "-orderPayStatus" ,orderPayStatus ,1800);
                }
                Date createTime = deliveryEntity.getCreateTime();
                LocalDateTime localDateTime = createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                LocalDateTime expirationTime = localDateTime.plusSeconds(expirationTimeInSeconds);
                //判断是否为未支付订单并且是否过期
                boolean nowAfter = now.isAfter(expirationTime);
                boolean equals = "0".equals(orderPayStatus);
                if (nowAfter && equals) {
                    //订单过期   修改状态
                    log.info("Find the order(" + id + ") is timeout and unpaid.Let close the order and timer.");
                    LambdaUpdateWrapper<DeliveryEntity> updateStatusWrapper = new LambdaUpdateWrapper<>();
                    updateStatusWrapper.set(DeliveryEntity::getStatus ,-2)
                            .eq(DeliveryEntity::getId ,id);
                    deliveryMapper.update(null ,updateStatusWrapper);
                    log.info("订单过期");
                    //清除Redis中unpaidOrderList过期的orderId
                    redisUtils.del("expressUnpaidOrder-" + id);
                    //关闭定时器
                    boolean cancelFlag = scheduledFutureMap.remove(id).cancel(true);
//                boolean cancelFlag = scheduledFuture.cancel(true);
                    if (cancelFlag == true) {
                        log.info("The timer for " + id + " had close.");
                    }
                }
                if (!("0".equals(orderPayStatus))) {
                    log.info("The order(" + id + ") status is other value.Let close the timer.");
                    //关闭定时器
//                scheduledFuture.cancel(true);
                    boolean cancelFlag = scheduledFutureMap.remove(id).cancel(true);
                }
            };
            // 假设立即开始检查，并仅执行一次
            ScheduledFuture<?> scheduledFuture = scheduler.scheduleWithFixedDelay(checkTask , 0,60 , TimeUnit.SECONDS);
            scheduledFutureMap.put(String.valueOf(id), scheduledFuture);
        }

        return insertCount;
    }

    /**
      *methood: 包裹分拣（以地址为依据
      *auth: cyx
      *time: 2024/6/26 15:09
    **/
    public DeliveryEntity differentiateOrders(List<DeliveryEntity> deliveryEntityList ,String nowAddress ,String uid){
        //生成订单号
        String orderNum = createOrderNum();
        //分拣true
        DeliveryEntity deliveryEntity = new DeliveryEntity();
        List<TGlPackageDetailsEntity> packageList = new ArrayList<>();
        for (int i = 0 ;i < deliveryEntityList.size() ;i ++){
            String customsClearance = deliveryEntityList.get(i).getCustomsClearance();
            String address = deliveryEntityList.get(i).getAddress();
            String productName = deliveryEntityList.get(i).getProductName();
            String trackingNumber = deliveryEntityList.get(i).getTrackingNumber();
            String unitPrice = deliveryEntityList.get(i).getUnitPrice();
            String numberOfPieces = deliveryEntityList.get(i).getNumberOfPieces();
            String plateNumber = deliveryEntityList.get(i).getPlateNumber();
            String expressCompany = deliveryEntityList.get(i).getExpressCompany();
            BigDecimal unitPriceDecimal = new BigDecimal(unitPrice);
            if (nowAddress.equals(address)){
                BeanUtils.copyProperties(deliveryEntityList.get(i) ,deliveryEntity);
                //将报关的boolean改为0或1
                if ("1".equals(customsClearance)){
                    deliveryEntity.setCustomsClearance("1");
                }else {
                    deliveryEntity.setCustomsClearance("0");
                }
                TGlPackageDetailsEntity tGlPackageDetailsEntity = new TGlPackageDetailsEntity();
                tGlPackageDetailsEntity.setDeliveryNumber(trackingNumber);
                if (tGlPackageDetailsEntity.getDeliveryNumber() == null){
                    tGlPackageDetailsEntity.setDeliveryNumber("-1");
                }
                tGlPackageDetailsEntity.setOrderNumber(orderNum);
                tGlPackageDetailsEntity.setProductName(productName);
                tGlPackageDetailsEntity.setCreateBy(uid);
                tGlPackageDetailsEntity.setCreateTime(new DateTime());
                tGlPackageDetailsEntity.setUnitPrice(unitPriceDecimal);
                if (!StringUtils.isEmpty(numberOfPieces)){
                    tGlPackageDetailsEntity.setNumberOfPieces(Integer.valueOf(numberOfPieces));
                }
                tGlPackageDetailsEntity.setPlateNumber(plateNumber);
                tGlPackageDetailsEntity.setExpressCompany(expressCompany);
                packageList.add(tGlPackageDetailsEntity);
            }
        }
        deliveryEntity.setOrderNumber(orderNum);
        deliveryEntity.setLists(packageList);
        deliveryEntity.setCreateTime(new DateTime());
        deliveryEntity.setCreateBy(uid);
        return deliveryEntity;
    }

    /**
      *methood: 订单支付
      *auth: cyx
      *time: 2024/6/7 15:51
    **/
//    @Override
//    @Transactional
//    public String payOrder(String id ,Long uid) {
//        //查询订单金额
//        LambdaQueryWrapper<DeliveryEntity> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.eq(DeliveryEntity::getId ,id);
//        DeliveryEntity deliveryEntity = deliveryMapper.selectOne(queryWrapper);
//        Double totalPrice = deliveryEntity.getFreight();
//        BigDecimal totalPriceBD = new BigDecimal(totalPrice);
//        //对比用户余额
//        YxUserQueryVo userQueryVo = yxUserService.getYxUserById(uid);
//        BigDecimal nowMoney = userQueryVo.getNowMoney();
//        Integer payCode = nowMoney.compareTo(totalPriceBD);
//        if (payCode < 0){
//            return "0";
//        }
//        //修改订单支付状态与订单状态
//        LambdaUpdateWrapper<DeliveryEntity> updateWrapper = new LambdaUpdateWrapper<>();
//        updateWrapper.eq(DeliveryEntity::getId ,id).set(DeliveryEntity::getPayment ,"1").set(DeliveryEntity::getStatus ,"3");
//        int updateCount = deliveryMapper.update(null, updateWrapper);
//        //修改余额
//        LambdaUpdateWrapper<YxUser> updateWrapperUser = new LambdaUpdateWrapper<>();
//        updateWrapperUser.eq(YxUser::getUid ,uid).set(YxUser::getNowMoney ,nowMoney.subtract(totalPriceBD));
//        yxUserMapper.update(null ,updateWrapperUser);
//        //插入账单
//        YxUserBill yxUserBill = new YxUserBill();
//        yxUserBill.setUid(uid);
//        yxUserBill.setLinkId("0");
//        yxUserBill.setPm(0);
//        yxUserBill.setTitle("包裹订单支付");
//        yxUserBill.setCategory("now_money");
//        yxUserBill.setType("pay_delivery");
//        yxUserBill.setNumber(totalPriceBD);
//        yxUserBill.setBalance(nowMoney.subtract(totalPriceBD));
//        yxUserBill.setMark("余额支付了" + totalPriceBD + "用于快递订单付款");
//        yxUserBill.setCreateTime(new Date());
//        yxUserBill.setStatus(1);
//        yxUserBillMapper.insert(yxUserBill);
//        return Integer.toString(updateCount);
//    }

    /**
      *methood: 生成订单号
      *auth: cyx
      *time: 2024/6/7 15:39
    **/
    public String createOrderNum(){
        // 生成一个0到999999之间的随机数（包含0，不包含999999）
        int randomNumber = ThreadLocalRandom.current().nextInt(0, 1000000);

        // 使用String.format来格式化数字，确保它总是6位（如果数字小于6位，则前面补0）
        String formattedNumber = String.format("%06d", randomNumber);

        // 添加前缀
        return "JQ" + formattedNumber;
    }

    @Override
    public void insertCity(){
        List<Map<String ,String>> list = new ArrayList<>();
//        String str = "河北省,山西省,辽宁省,吉林省,黑龙江省,江苏省,浙江省,安徽省,福建省,江西省,山东省,河南省,湖北省,湖南省,广东省,海南省,四川省,贵州省,云南省,陕西省,甘肃省,青海省,台湾省,内蒙古自治区,广西壮族自治区,西藏自治区,宁夏回族自治区,新疆维吾尔自治区,北京市,天津市,上海市,重庆市,香港特别行政区,澳门特别行政区";
        //越南
//        String str = "河江省,宣光省,高平省,谅山省,莱州省,老街省,安沛省,北江省,太原省,广宁省,富寿省,永福省,北宁省,海阳省,兴安省,太平省,河南省,南定省,宁平省,清化省,宜安省,河静省,广平省,广治省,承天-顺化省,广义省,平定省,富安省,广和省,宁顺省,平顺省,昆嵩省,嘉莱省,多乐省,林同省,平阳省,平福省,西宁省,同奈省,隆安省,同塔省,安江省,前江省,槟木知省,永隆省,茶荣省,芹苴省,朔庄省,坚江省,薄寮省,金瓯省,巴地-头顿省,河内市,胡志明市,岘港市,海防市,芹苴市";
        //老挝
//        String str = "万象省,丰沙里省,琅南塔省,波乔省,乌多姆赛省,琅勃拉邦省,华潘省,沙耶武里省,川圹省,波里坎赛省,阿速坡省,占巴塞省,色贡（公河）省,沙拉湾省,沙湾拿吉省,甘蒙省,赛宋本行政特区,万象市";
        //柬埔寨
//        String str = "马德望省,贡布省,干丹省,磅湛省,磅清扬省,磅士卑省,磅同省,桔井省,波罗勉省,班迭棉吉省,暹粒省,上丁省,茶胶省,柴桢省,蒙多基里省,柏威夏省,戈公省,奥多棉吉省,菩萨省,腊塔纳基里省,金边市,西哈努克市,白马市,拜林市";
        //泰国
//        String str = "曼谷,清迈府,清莱府,甘烹碧府,南邦府,南奔府,夜丰颂府,北榄坡府,楠府,帕尧府,碧差汶府,披集府,彭世洛府,帕府,素可泰府,达府,乌泰他尼府,程逸府,安纳乍能府,武里南府,猜也奔府,加拉信府,孔敬府,黎府,玛哈沙拉堪府,莫拉限府,那空帕侬府,呵叻府,廊磨喃蒲府,廊开府,横逸府,色军府,素辇府,乌汶府,莫肯府,益梭通府,那空那育府,红统府,大城府,猜纳府,北碧府,华富里府,坤西育府,佛统府,暖武里府,巴吞他尼府,北揽府,信武里府,素攀武里府,龙仔厝府,北标府,叻丕府,佛丕府,猜那府,尖竹汶府,春武里府,巴真府,罗勇府,沙缴府,桐艾府,北大年府,也拉府,陶公府,宋卡府";
        //缅甸
//        String str = "伊洛瓦底省,勃固省,马圭省,曼德勒省,实皆省,德林达依省,仰光省,钦邦,克钦邦,克耶邦,克伦邦,孟邦,若开邦,掸邦,内比都,仰光市";
        //马来西亚
//        String str = "吉打州,吉兰丹州,槟城州,霹雳州,雪兰莪州,森美兰州,马六甲州,柔佛州,砂拉越州,沙巴州,彭亨州,玻璃市州,登嘉楼州,吉隆坡,纳闽,布城";
        //文莱
//        String str = "文莱-摩拉区,马来奕区,都东区,淡布隆区";
        //菲律宾
        String str = "阿布拉省，北阿古桑省，南阿古桑省，阿克兰省，阿尔拜省，安蒂克省，阿巴尧省，奥罗拉省，巴西兰省，巴坦省，巴坦群岛省，八打雁省，本格特省，比利兰省，保和省，布基农省，布拉干省，卡加延省，北甘马粦省，南甘马粦省，甘米银省卡皮斯省，卡坦端内斯省，甲米地省，宿务省，康波斯特拉谷省，哥打巴托省，北达沃省，南达沃省，西达沃省，东达沃省，迪纳加特群岛省，东萨马省，吉马拉斯省，伊富高省，北伊罗戈省，南伊罗戈省，伊洛伊洛省，伊莎贝拉省，卡林阿省，拉乌尼翁省，内湖省,北拉瑙省，南拉瑙省，莱特省，马京达瑙省，马林杜克省，马斯巴特省，马尼拉都会区，西米萨米斯省，东米萨米斯省，高山省，西内格罗斯省，东内格罗斯省，北萨马省，新怡诗夏省，新比斯开省，西民都洛省，东民都洛省，巴拉望省，邦板牙省，班诗兰省，奎松省,季里诺省，黎刹省，朗布隆省，萨马省，萨兰加尼省，锡基霍尔省，索索贡省，南哥打巴托省，南莱特省，苏丹库达拉省，苏禄省，北苏里高省，南苏里高省，丹辘省，塔威塔威省，三描礼士省，北三宝颜省，南三宝颜省，宝颜锡布格省，马拉维市";
        String s = str.replace("，" ,",");
        //印尼
//        String str = "亚齐特区,巴厘省,邦加-勿里洞省,万丹省,明古鲁省,中爪哇省,中加里曼丹省,中巴布亚省,中苏拉威西省,东爪哇省,东加里曼丹省,东努沙登加拉省,哥伦打洛省,高地巴布亚省,雅加达首都特区,占碑省,楠榜省,马鲁古省,北加里曼丹省,北马鲁古省,北苏拉威西省,北苏门答腊省,巴布亚省,廖内省,廖内群岛省,东南苏拉威西省,南加里曼丹省,南巴布亚省,南巴布亚省,南苏拉威西省,南苏门答腊省,南苏门答腊省,西爪哇省,西加里曼丹省,西努沙登加拉省,西巴布亚省,西苏拉威西省,西苏门答腊省,日惹特区";
        String[] splitArr = s.split(",");
        int j = 298;
        for (int i = 0 ;i < splitArr.length ;i ++){
            Map<String, String> map = new HashMap<>();
            map.put("name" ,splitArr[i]);
            map.put("mergerName" ,splitArr[i]
//                                            .replace("省" ,"")
//                                            .replace("市","")
//                                            .replace("府" ,"")
//                                            .replace("邦" ,"")
                                            + ",菲律宾");
            map.put("parentId" ,"11");
            map.put("level" ,"1");
            map.put("cityId" ,Integer.toString(j));
            j++;
            list.add(map);
        }
        deliveryMapper.insertCity(list);
    }

    @Override
    public int uploadPaymentUrl(String url ,String deliveryId) {
        LambdaUpdateWrapper<DeliveryEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(DeliveryEntity::getPaymentScreenshot ,url)
                .set(DeliveryEntity::getPayment ,"1")
                .eq(DeliveryEntity::getId ,deliveryId);
        int updateCount = deliveryMapper.update(null, updateWrapper);
        return updateCount;
    }

    @Override
    public void paySuccess(String deliveryOrderId) {
        LambdaUpdateWrapper<DeliveryEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(DeliveryEntity::getStatus ,"2")
                .eq(DeliveryEntity::getId ,deliveryOrderId);
        int updateCount = deliveryMapper.update(null, updateWrapper);
        log.info("订单完成付款");
    }

    /**
     *methood: 根据单号查快递订单
     *auth: cyx
     *time: 2024/11/30 14:29
     **/
    @Override
    public List<DeliveryEntity> listByOrderNumber(String number) {
        List<DeliveryEntity> deliveryList = deliveryMapper.listByOrderNumber(number);
        return deliveryList;
    }

    /**
     * methood: 确认收货
     * auth: cyx
     * time: 2024/11/30 16:41
     **/
    @Override
    @Transactional
    public Map receive(String orderId, Long userId) {
        LambdaUpdateWrapper<DeliveryEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(DeliveryEntity::getStatus ,"5")
                .eq(DeliveryEntity::getId ,orderId);
        int updateCount = deliveryMapper.update(null, updateWrapper);

        Map<String, String> map = new HashMap<>();
        if (updateCount < 1){
            map.put("result","确认收货失败");
            return map;
        }

        // 按重量转化积分,1kg=1积分,
        DeliveryEntity deliveryEntity = deliveryMapper.getDeliverDetail(orderId);

        BigDecimal weight = new BigDecimal(String.valueOf(deliveryEntity.getLists().get(0).getWeight()));
//        BigDecimal point = weight.setScale(0, BigDecimal.ROUND_FLOOR);
        SysUser user = userMapper.selectUserById(userId);

        // 新增积分日志
        TPointsLog tPointsLog = new TPointsLog();
        tPointsLog.setAddMethod(0);
        tPointsLog.setAddPoints(weight);
        tPointsLog.setCreateTime(new Date());
        tPointsLog.setCreateBy(user.getUserName());

        int pointLog = tPointsLogMapper.insert(tPointsLog);

        // 若新增日志失败，直接返回
        if (pointLog < 0){
            log.error("积分日志新增操作失败");
            map.put("result","签到日志新增操作失败");
            return map;
        }

        // 修改积分
        BigDecimal points = user.getPoints().add(weight);
        user.setPoints(points);
        int account =  userMapper.updateUser(user);

        map.put("result","签到成功");
        map.put("points",weight.toString());
        return map;
    }

    /**
      *methood: 生成二维码
      *auth: cyx
      *time: 2024/12/5 8:39
    **/
    @Override
    public String createQrcode(String orderNumber) {
        String filePath = codePath + "/qrcode_" + orderNumber + ".png";

        QrUtil qrUtil = new QrUtil();
        QRCodeParameter parameter = new QRCodeParameter();
        parameter.setHouseId(101L);
//            parameter.setQrcodeInitValue("index");
        parameter.setQrcodePrefix(orderNumber);

        /// String logoImgPath = null;
        String logoImgPath = "C:\\\\Users\\\\os\\\\Desktop\\\\文件\\\\图片\\\\logo.png";
        String path = qrUtil.generateQRCode(parameter, logoImgPath ,filePath);

        return path;
    }

    /**
      *methood: 生成条形码
      *auth: cyx
      *time: 2024/12/5 16:21
    **/
    @Override
    public String createBarcode(String orderNumber ,String id) {
        String filePath = codePath + "/barcode_" + orderNumber + "_" + id + ".png";
        // 条形码图片的宽度和高度
        int width = 800;
        int height = 100;

        try {
            // 生成条形码
            BitMatrix bitMatrix = new MultiFormatWriter().encode(
                    id,
                    BarcodeFormat.CODE_128,
                    width,
                    height
            );

            // 保存条形码为图片
            Path path = new File(filePath).toPath();
            MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);

            log.info("条形码已生成，保存路径: " + filePath);
        } catch (Exception e) {
            log.error("生成条形码时发生错误: " + e.getMessage());
            e.printStackTrace();
        }
        return filePath;
    }

    /**
     *methood: 根据包裹id查询订单及包裹信息
     *auth: cyx
     *time: 2024/12/6 13:54
     **/
    @Override
    public DeliveryEntity selectOrderByPackageId(String packageId) {
        DeliveryEntity deliveryEntity = deliveryMapper.detailByPackageId(packageId);
        return deliveryEntity;
    }

    @Async("taskExecutor")
    public AjaxResult inOrOutAsync(String packageId ,String type) {
        LambdaUpdateWrapper<DeliveryEntity> updateWrapper = new LambdaUpdateWrapper<>();
        DeliveryEntity deliveryEntity = deliveryMapper.detailByPackageId(packageId);
        String packageStatus = deliveryEntity.getLists().get(0).getInOrOut();
        String deliveryStatus = deliveryEntity.getStatus();
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("interfaceType" ,"inOrOut");
        if (ScanTypeEnum.IN.getValue().equals(type) && (!PackageStatusEnum.WAIT_IN.getValue().equals(packageStatus))) {
            //已入库   入库操作
            return AjaxResult.error("已入库" ,resultMap);
        } else if (ScanTypeEnum.IN.getValue().equals(type) && PackageStatusEnum.WAIT_IN.getValue().equals(deliveryStatus)) {
            //未入库   入库操作
            //修改包裹状态
            deliveryMapper.changePackageStatus(packageId ,PackageStatusEnum.IN_OK.getValue());
            //查询订单所有包裹状态 都为入库则订单状态为入库
            Boolean checkAllIn = checkAllIn(packageId);
            if (checkAllIn) {
                updateWrapper.clear();
                updateWrapper.eq(DeliveryEntity::getId ,deliveryEntity.getId())
                        .set(DeliveryEntity::getStatus ,OrderStatusEnum.WAIT_FULL.getValue());
                deliveryMapper.update(null ,updateWrapper);
            }
            resultMap.put("resultOrderNumber" ,deliveryEntity.getOrderNumber());
            return AjaxResult.success("入库成功" ,resultMap);
        } else if (ScanTypeEnum.OUT.getValue().equals(type) && PackageStatusEnum.IN_OK.getValue().equals(packageStatus)) {
            //已入仓未出库    进行出库操作
            deliveryMapper.changePackageStatus(packageId ,PackageStatusEnum.OUT_OK.getValue());
            //查询订单所有包裹状态 都为出库库则订单状态为出库
            Boolean checkAllOut = checkAllOut(packageId);
            if (checkAllOut) {
                updateWrapper.clear();
                updateWrapper.eq(DeliveryEntity::getId ,deliveryEntity.getId())
                        .set(DeliveryEntity::getStatus ,OrderStatusEnum.WAIT_RECEIVE.getValue());
                deliveryMapper.update(null ,updateWrapper);
            }
            resultMap.put("resultOrderNumber" ,deliveryEntity.getOrderNumber());
            return AjaxResult.success("出库成功" ,resultMap);
        } else if (ScanTypeEnum.OUT.getValue().equals(type) && PackageStatusEnum.WAIT_IN.getValue().equals(packageStatus)) {
            //未入库   出库操作
            return AjaxResult.error("未入库" ,resultMap);
        }
        return AjaxResult.warn("出错了，请稍后再试" ,resultMap);
    }

    /**
     *methood: 扫码出入库
     *auth: cyx
     *time: 2024/12/6 19:20
     **/
    @Override
    @Transactional
    public AjaxResult inOrOutByScan(String packageId , String type) {
        return inOrOutAsync(packageId ,type);
    }

    /**
      *methood: 检查是否都已入库
      *auth: cyx
      *time: 2024/12/7 9:53
    **/
    public Boolean checkAllIn(String packageId) {
        DeliveryStatusVo deliveryStatusVo = deliveryMapper.selectDeliveryStatus(packageId);
        List<PackageStatusVo> packageStatusList = deliveryStatusVo.getPackageStatusList();
        for (PackageStatusVo packageStatusVo : packageStatusList) {
            if (Integer.valueOf(packageStatusVo.getInOrOut()) < Integer.valueOf(PackageStatusEnum.IN_OK.getValue())) {
                return false;
            }
        }
        return true;
    }

    /**
     *methood: 检查是否都已出库
     *auth: cyx
     *time: 2024/12/7 9:53
     **/
    public Boolean checkAllOut(String packageId) {
        DeliveryStatusVo deliveryStatusVo = deliveryMapper.selectDeliveryStatus(packageId);
        List<PackageStatusVo> packageStatusList = deliveryStatusVo.getPackageStatusList();
        for (PackageStatusVo packageStatusVo : packageStatusList) {
            if (Integer.valueOf(packageStatusVo.getInOrOut()) < Integer.valueOf(PackageStatusEnum.OUT_OK.getValue())) {
                return false;
            }
        }
        return true;
    }
}
